package com.infore.dataAudit.select;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.infore.dataAudit.enums.ResultStatus;
import com.infore.dataAudit.select.dto.QueryParamDto;
import com.infore.dataAudit.select.util.QueryUtil;
import com.infore.dataAudit.util.Constants;
import com.infore.dataAudit.util.Page;
import com.infore.dataAudit.util.ResultEntity;

@Component
public class QueryDispatcher {

	@Autowired
	EntityManager entityManager;

	/**
	 * 查询分发器，入口
	 * 
	 * @param entityManager
	 */
	public ResultEntity dispatcher(QueryParamDto queryParamDto, Class<?> clz) {
		// 构建查询对象
		CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();// 用于构建CriteriaQuery和构建和组装查询条件
		CriteriaQuery<Tuple> query = criteriaBuilder.createTupleQuery();// 用于组装查询实体
		Root<?> root = query.from(clz);// 包装对象，用于获取被包装对象的属性
		// 构建查询条件
		List<Predicate> predicates = QueryUtil.createQueryCondition(queryParamDto, criteriaBuilder, root);
		// 组装查询条件
		Predicate predicate = QueryUtil.assembleCondition(queryParamDto, criteriaBuilder, predicates);
		// 组装SQL
		QueryUtil.assembleSql(queryParamDto, criteriaBuilder, query, root, predicate);
		// 获取查询结果
		TypedQuery<Tuple> typedQuery = entityManager.createQuery(query);
		List<?> result = typedQuery.getResultList();
		// 获取分页结果
		Page<Map<String, Object>> page = new Page<>();
		result = QueryUtil.getPage(result.size(), result, typedQuery, queryParamDto, page);
		// 封装查询结果
		List<Map<String, Object>> list = new ArrayList<>(); // 结果集
		List<String> selects = Arrays.asList(queryParamDto.getAssembleSql().getSelect().split(","));
		for (Object tuple : result) {
			Map<String, Object> map = new HashMap<>();
			for (int i = 0; i < selects.size(); i++) {
				String filed = selects.get(i).toString();
				if (filed.contains(".")) { //将数据点对象等形式改成下划线形式,以便前端方便解析
					filed = filed.replace(".", "_");
				}
				Object object = ((Tuple) tuple).get(i);
				// 判断是否为时间类型,将其转换为字符串
				if (object.getClass().equals(Timestamp.class)) {
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					map.put(filed, sdf.format(object));
				} else {
					map.put(filed, object);
				}
			}
			list.add(map);
		}
		if (queryParamDto.getPageObject() != null) {
			page.setList(list);
			return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setPage(page);
		} else {
			return new ResultEntity(ResultStatus.SUCCESS, Constants.QUERY_SUCCESS).setDataList(list);
		}
	}
}
